#include <SFML/Graphics/CircleShape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <FanShape.h>
#include <nice2d/spritedecorator.h>
#include <nice2d/sprite.h>
#include <nice2d/util.h>

IMPLEMENT_OBJECT(SpriteDecorator,Serializer)

class SpriteDecoratorData
{
public:
    SpriteWeakPointer sprite;
};

SpriteDecorator::SpriteDecorator():
    data(new SpriteDecoratorData)
{
}

SpriteDecorator::~SpriteDecorator()
{
}

void SpriteDecorator::setSprite(SpritePointer sprite)
{
    data->sprite = sprite;
}

SpriteWeakPointer SpriteDecorator::getSprite() const
{
    return data->sprite;
}

/*
IMPLEMENT_OBJECT(SpriteRingDecorator,SpriteDecorator)

class SpriteRingData
{
public:
    SpriteRingData()
    {
        circle.setPointCount(100);
        circle.setFillColor(sf::Color::Transparent);
        circle.setOutlineThickness(2.4f);
        circle.setOutlineColor(sf::Color::Blue);
    }

    float scaleFactor = 1.0f;
    sf::CircleShape circle;
};

SpriteRingDecorator::SpriteRingDecorator(SpritePointer sprite):
    SpriteDecorator(sprite),
    data(new SpriteRingData())
{
}

SpriteRingDecorator::~SpriteRingDecorator()
{
}

void SpriteRingDecorator::setScaleFactor(float factor)
{
    if (factor > 0.0f)
        data->scaleFactor = factor;
}

float SpriteRingDecorator::getScaleFactor()const
{
    return data->scaleFactor;
}

void SpriteRingDecorator::setOutlineThickness(float thickness)
{
    data->circle.setOutlineThickness(thickness);
}

float SpriteRingDecorator::getOutlineThickness()const
{
    return data->circle.getOutlineThickness();
}

void SpriteRingDecorator::setOutlineColor(const sf::Color &color)
{
    data->circle.setOutlineColor(color);
}

sf::Color SpriteRingDecorator::getOutlineColor()const
{
    return data->circle.getOutlineColor();
}

void SpriteRingDecorator::setFillColor(const sf::Color &color)
{
    data->circle.setFillColor(color);
}

sf::Color SpriteRingDecorator::getFillColor()const
{
    return data->circle.getFillColor();
}

PTree SpriteRingDecorator::serialize()
{
    PTree node;
    node.add("scaleFactor", getScaleFactor());
    node.add("outlineThickness", getOutlineThickness());
    node.add_child("outlineColor",serializeObject(getOutlineColor()));
    node.add_child("fillColor",serializeObject(getFillColor()));
    return node;
}

void SpriteRingDecorator::deserialize(const PTree &node)
{
    setScaleFactor(node.get<float>("scaleFactor"));
    setOutlineThickness(node.get<float>("outlineThickness"));
    setOutlineColor(deserializeColor(node.get_child("outlineColor")));
    setFillColor(deserializeColor(node.get_child("fillColor")));
}

void SpriteRingDecorator::update()
{
    auto box = getSprite()->getBoundingBox();
    std::cout<<"sprite box:"<<box.left<<" "<<box.top<<" "<<box.width<<" "<<box.height<<std::endl;

    auto spriteCenter = getRectCenter(box);
    float radius = distance(spriteCenter,sf::Vector2f(box.left,box.top)) * data->scaleFactor;
    data->circle.setRadius(radius);
    auto circleBox = data->circle.getLocalBounds();
    std::cout<<circleBox.left<<" "<<circleBox.top<<" "<<circleBox.width<<" "<<circleBox.height<<std::endl;

    //auto position = Entity::adjustPosition({0.0f,0.0f,box.width,box.height},sf::Vector2f(circleBox.width,circleBox.height),HMode_Center,VMode_Center,0.0f,0.0f);
    //data->circle.setPosition(position-getRectCenter(box)+getRectCenter(circleBox)+sf::Vector2f(circleBox.left,circleBox.top));//+sf::Vector2f(circleBox.left,circleBox.top));
    data->circle.setPosition(-circleBox.left,-circleBox.top);
    //data->circle.setPosition(position+sf::Vector2f(circleBox.left,circleBox.top));//-getRectCenter(circleBox));
}

void SpriteRingDecorator::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
    target.draw(data->circle, states);
}

IMPLEMENT_OBJECT(SpriteFanShapeDecorator,SpriteDecorator)

class SpriteFanShapeDecoratorData
{
public:
    FanShape fan;
    Sprite *sprite = nullptr;
    float includeAngle = 60.0f;
};

SpriteFanShapeDecorator::SpriteFanShapeDecorator(SpritePointer sprite):
    SpriteDecorator(sprite),
    data(new SpriteFanShapeDecoratorData())
{
}

SpriteFanShapeDecorator::~SpriteFanShapeDecorator()
{
}

void SpriteFanShapeDecorator::setRadius(float radius)
{
    if (radius < .0f)
        return;
    data->fan.setRadius(radius);
}

float SpriteFanShapeDecorator::getRadius() const
{
    return data->fan.getRadius();
}

void SpriteFanShapeDecorator::setIncludedAngle(float angle)
{
    if (angle <= 0.0f)
        return;

    data->includeAngle = angle;
}

float SpriteFanShapeDecorator::getIncludedAngle()const
{
    return data->includeAngle;
}

void SpriteFanShapeDecorator::setOutline(const sf::Color &color, float thickness)
{
    data->fan.setOutlineColor(color);
    data->fan.setOutlineThickness(thickness);
}

void SpriteFanShapeDecorator::setFillColor(const sf::Color &color)
{
    data->fan.setFillColor(color);
}

sf::Color SpriteFanShapeDecorator::getFillColor()const
{
    return data->fan.getFillColor();
}

PTree SpriteFanShapeDecorator::serialize()
{
    PTree node;
    node.add("radius", data->fan.getRadius());
    node.add("includedAngle", getIncludedAngle());
    node.add("outlineThickness", data->fan.getOutlineThickness());
    node.add_child("outlineColor",serializeObject(data->fan.getOutlineColor()));
    node.add_child("fillColor",serializeObject(getFillColor()));
    return node;
}

void SpriteFanShapeDecorator::deserialize(const PTree &node)
{
    setRadius(node.get<float>("radius"));
    setIncludedAngle(node.get<float>("includeAngle"));
    data->fan.setOutlineThickness(node.get<float>("outlineThickness"));
    data->fan.setOutlineColor(deserializeColor(node.get_child("outlineColor")));
    setFillColor(deserializeColor(node.get_child("fillColor")));
}

void SpriteFanShapeDecorator::update()
{
    const auto sprite = getSprite();
    float angle = sprite->getRotate();
    float radius = data->fan.getRadius();

    data->fan.setRangeAngle(angle - data->includeAngle * 0.5f,
                            angle + data->includeAngle * 0.5f);
    data->fan.setPosition(sprite->getPosition() - sf::Vector2f(radius, radius) - sprite->getSize()*0.5f);
}

void SpriteFanShapeDecorator::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
    states.transform = sf::Transform();
    target.draw(data->fan, states);
}

*/
